<?php

/**
 * @author Thibaut Cromphaut, Gaïtano Boeraeve, Mathias Helin, Dimitry Dierickx
 * @copyright  Copyright (c) 2011 Artevelde University College Ghent 
 */

class Application_Model_UserMapper extends Ahs_Model_Mapper
{
    
    public function __construct(array $options = null)
    {
        parent::__construct($options);
        $this->DbTableName = 'Application_Model_DbTable_Users';
        $this->PropertiesMap = array
        (
            "Id"                => "user_id",
            "Givenname"         => "user_givenname",
            "Familyname"        => "user_familyname",
            "Password"          => "user_password",
            "RoleId"            => "user_role_id",
            "Avatar"            => "user_avatar",
            "Title"             => "user_title",
            "Bio"               => "user_bio",
            "Addressline"       => "user_addressline",
            "Postcode"          => "user_postcode",
            "City"              => "user_city",
            "CountryId"         => "country_id",
            "Dob"               => "user_dob",
            "SecretQuestionId"  => "secretquestions_secretquestion_id",
            "SecretAnswer"      => "user_secretanswer",
            "Prefnewsletter"    => "user_pref_newsletter",
            "ActiveDate"        => "user_activedate",
            "CreationDate"      => "user_creationdate",
            "ModifiedDate"      => "user_modifieddate",
            "DeletedDate"       => "user_deleteddate",
            "LastloginDate"     => "user_lastlogindate",
        );
    }
    
    /**
     * Get all users
     * 
     * @param integer $page_nr      If you wish to use paging, pass the page-number. To disable paging, 
     *                              pass null as value (default) and return all rows.
     * @param integer $nr_results   The number of results per page, defaults to 10.
     * @return Array(Application_Model_User)
     */
    public function fetchAll($page_nr=null, $nr_results=10)
    {        
        $table = $this->getDbTable();
        $select = $table->select();
        $select->where(''.$this->getColumn('DeletedDate').' IS NULL')
               ->order(''.$this->getColumn('Givenname').' ASC');
        
        if($page_nr != null && $page_nr > 0)
            $select->limitPage($page_nr, $nr_results);
        
        $rows = $table->fetchAll($select);
        return $this->_toUsers($rows);
    }

    /**
     * Get a user by its ID
     * 
     * @param integer $id
     * @return Application_Model_Announcement
     */
    public function fetchById($id)
    {
        $row = $this->getDbTable()->fetchRow(array(''.$this->getColumn('Id').' = ?' => $id));
        return $this->_toUser($row);
    }
    
    /**
     * Search users by (part of their) name (=> Givenname[ ]Familyname)
     * 
     * @param string $name
     * @param integer $limit
     * @return Array(Application_Model_User) 
     */
    public function findByName($name, $limit=false)
    {
        $table  = $this->getDbTable();
        $select = $table->select();
        $where  = $table->getAdapter()->quoteInto(
                    'CONCAT('.$this->getColumn('Givenname').', " ", '.$this->getColumn('Familyname').', " ", '.$this->getColumn('Givenname').') LIKE ?', '%'.$name.'%'
                        . ' AND ' .
                    ''.$this->getColumn('DeletedDate').' IS NULL'
        );
        $select->where($where)
               ->order(''.$this->getColumn('Givenname').' ASC');
        if($limit !== false && $limit > 0)
        {
            $select->limit($limit);
        }
        $rows = $table->fetchAll($select);
        return $this->_toAnnouncements($rows);
    }
    
    /**
     * Get a single user by e-mail
     * 
     * @param string $email
     * @return Application_Model_User
     */
    public function fetchByEmail($email)
    {
        $table = $this->getDbTable();
        $select = $table->select()->setIntegrityCheck(false);
        $select->from(
                    array('users' => 'users'),
                    "*"
                )
               ->joinInner(
                    array('mail' => 'users_has_emails_types'),
                    'users.user_id=mail.users_user_id',
                    '*'
                 )
               ->where('mail.user_has_email = :email')
               ->bind(array(':email' => $email));
        $row  = $table->fetchRow($select);
        
        return $this->_toUser($row);   
    }
    
    /**
     * Search users by (part of their) email
     * 
     * @param string $email
     * @param integer $limit
     * @return Array(Application_Model_User) 
     */
    public function findByEmail($email, $limit=false)
    {
        $table = $this->getDbTable();

        $select = $table->select()->setIntegrityCheck(false);
        $select->from('users')->joinInner(array('mail' => 'users_has_emails_types'),'users.user_id=mail.users_user_id')
               ->where('mail.user_has_email LIKE :email')
               ->bind( array(':email' => "%{$email}%") )
               ->order('mail.user_has_email ASC');
        if($limit !== false && $limit > 0)
        {
            $select->limit($limit);
        }
        $rows = $table->fetchAll($select);
    
        return $this->_toUsers($rows);
    }
    
    /**
     * Get the total number of users
     * 
     * @return integer
     */
    public function getCount()
    {
        $ids    = array();
        
        $table = $this->getDbTable();
        $select = $table->select();
        $select->from($table, array('count(*) as count'));
        $select->where(''.$this->getColumn('DeletedDate').' IS NULL');
        
        $rows = $table->fetchAll($select);
        
        return $rows[0]->count;
    }
    
    /**
     * Get a list of book_ids the user is subscribed to
     * 
     * @param integer $user_id
     * @return Array 
     */
    public function getUserBookIds($user_id)
    {
        $result = array();
        $table  = new Application_Model_DbTable_UserHasBooks();
        $select = $table->select()->where('users_user_id = ?', $user_id);
        $rows = $table->fetchAll($select);
        if($rows)
        {
            foreach($rows as $row)
            {
                $result[]   = $row['books_book_id'];
            }
        }
        
        return $result;
    }
    
    /**
     * Get a list of course ids the user is subscribed to
     * 
     * @param integer $user_id
     * @return Array 
     */
    public function getUserCourseIds($user_id)
    {
        $result = array();
        $table  = new Application_Model_DbTable_UserHasCourses();
        $select = $table->select()->where('users_user_id = ?', $user_id);
        $rows = $table->fetchAll($select);
        if($rows)
        {
            foreach($rows as $row)
            {
                $result[]   = $row['courses_course_id'];
            }
        }
        
        return $result;
    }
    
    /**
     * Get the number of followers for a course
     * 
     * @param integer $course_id
     * @return Array 
     */
    public function getCountByCourseId($course_id)
    {
        $table = $this->getDbTable();
        $select = $table->select()->setIntegrityCheck(false);
        $select->from($table, array('count(*) as count'));
        $select->joinInner(array('uhc' => 'users_has_courses'),'users.'.$this->getColumn('Id').'=uhc.users_user_id')
               ->where(
                    'uhc.courses_course_id = :id'
                       . ' AND ' .
                    'users.'.$this->getColumn('DeletedDate').' IS NULL'
                 )
               ->bind(array(':id' => $course_id));
        $rows = $table->fetchAll($select);
        
        return $rows[0]->count;
    }
    
    /**
     * Add a course to the user's readinglist
     * 
     * @param integer $course_id
     * @param integer $user_id 
     */
    public function addCourseToUser($course_id, $user_id)
    {
        $table  = new Application_Model_DbTable_UserHasCourses();
        $table->insert(array(
            "courses_course_id" => $course_id,
            "users_user_id"     => $user_id,
        ));
    }
    
    /**
     * Delete a course from the user's readinglist
     * 
     * @param integer $course_id
     * @param integer $user_id 
     */
    public function deleteCourseFromUser($course_id, $user_id)
    {
        $table   = new Application_Model_DbTable_UserHasCourses();
        $db      = $table->getDefaultAdapter();
        $where[] = $db->quoteInto('courses_course_id = ?', $course_id);
        $where[] = $db->quoteInto('users_user_id = ?',     $user_id);
        $table->delete($where);
    }
    
    /**
     * Add a book to the user's readinglist
     * 
     * @param integer $book_id
     * @param integer $user_id 
     */
    public function addBookToUser($book_id, $user_id)
    {
        $table  = new Application_Model_DbTable_UserHasBooks();
        $table->insert(array(
            "books_book_id"     => $book_id,
            "users_user_id"     => $user_id,
        ));
    }
    
    /**
     * Remove a book from the user's readinglist
     * 
     * @param integer $book_id
     * @param integer $user_id 
     */
    public function deleteBookFromUser($book_id, $user_id)
    {
        $table  = new Application_Model_DbTable_UserHasBooks();
        $db      = $table->getDefaultAdapter();
        $where[] = $db->quoteInto('books_book_id = ?', $book_id);
        $where[] = $db->quoteInto('users_user_id = ?', $user_id);
        $table->delete($where);
    }
    
    /**
     * Save a user
     *
     * @param Application_Model_User $user
     */
    public function save(Application_Model_User $user)
    {
        $user_id = $user->Id;
        
        $data = $this->_getTableValues($user, array("Id"));
        $data[$this->getColumn("ModifiedDate")] = new Zend_Db_Expr('NOW()');
        
        if(null == $user_id)
        {
            // Set some default values
            $data[$this->getColumn("CreationDate")] = new Zend_Db_Expr('NOW()');
            $data[$this->getColumn("ActiveDate")]   = new Zend_Db_Expr('NOW()');
        
           $user_id = $this->getDbTable()->insert($data);
        }
        else
        {
            $this->getDbTable()->update($data, array(''.$this->getColumn('Id').' = ?' => $user_id));
        }
        
        return $user_id;
    }
    
    /**
     * Delete a user by id
     *
     * @param integer $id
     */
    public function delete($id)
    {   
        if (null != $id)
        {
            $data[$this->getColumn('DeletedDate')] = new Zend_Db_Expr('NOW()');
            $this->getDbTable()->update($data, array(''.$this->getColumn('Id').' = ?' => $id));
        }
    }
    
    /**
     * Undelete a user by id
     *
     * @param integer $id
     */
    public function undelete($id)
    {   
        if (null != $id)
        {
            $data[$this->getColumn('DeletedDate')] = new Zend_Db_Expr('NULL');
            $this->getDbTable()->update($data, array(''.$this->getColumn('Id').' = ?' => $id));
        } 
    }
    
    /**
     * Active a user by id
     *
     * @param integer $id
     */
    public function activate($id)
    {   
        if (null != $id)
        {
            $data[$this->getColumn('ActiveDate')] = new Zend_Db_Expr('NOW()');
            $this->getDbTable()->update($data, array(''.$this->getColumn('Id').' = ?' => $id));
        }
    }
    
    /**
     * Deactivate a user by id
     *
     * @param integer $id
     */
    public function deactive($id, $time=7)
    {   
        if (null != $id)
        {
            $data[$this->getColumn('ActiveDate')] = new Zend_Db_Expr('CURDATE() + INTERVAL '.$time.' DAYS');
            $this->getDbTable()->update($data, array(''.$this->getColumn('Id').' = ?' => $id));
        } 
    }
    
    /**
     * Change last login date
     * 
     * @param integer $id
     */
    public function updateLastLoginDate($id)
    {
       if (null != $id)
        {
            $data[$this->getColumn('LastloginDate')] = new Zend_Db_Expr('NOW()');
            $this->getDbTable()->update($data, array(''.$this->getColumn('Id').' = ?' => $id));
        } 
    }
    
    /**
     * Convert a row to object
     * 
     * @param Zend_Db_Table_Row_Abstract $row
     * @return Application_Model_User
     */
    private function _toUser(Zend_Db_Table_Row_Abstract $row = null)
    {
        // Create our object
        $object = new Application_Model_User();
        
        // Only go on if we actually have a row
        if($row)
        {
            // We have a propertiesmap, let's try to map it back to an object
            foreach($this->PropertiesMap as $key=>$column)
            {
                if(isset($row[$column]))
                    $object->$key      = $row[$column];
            }
        }

        return $object;
    }

    /**
     * Convert a rowset to an array of objects
     * 
     * @param Zend_Db_Table_Rowset_Abstract $rows
     * @return Array(Application_Model_User)
     */
    private function _toUsers(Zend_Db_Table_Rowset_Abstract $rows = null)
    {
        $results = array();
        if ($rows)
        {
            foreach ($rows as $row)
            {
                $results[] = $this->_toUser($row);
            }
        }
        return $results;
    }
}